﻿// **********************************************************************
//
// Author: KingSley
// Email:3268374537@qq.com
// Created:	2018/8/1   09:20
// Introduce: 时间管理工具
//
// **********************************************************************
using System.Reflection;
using System;
using System.Collections.Generic;

namespace KingSley
{
    /// <summary>
    /// 时间的获取与时差的计算
    /// </summary>
    public class TimeUtil
    {
        public struct TimeData
        {
            public int year;
            public int month;
            public int day;
            public int hour;
            public int minute;
            public int second;
        };

        /// <summary>
        /// 获取Int64类型当前时间，单位秒
        /// </summary>
        /// <returns>当前时间</returns>
        public static Int64 getSystemMilliSecond()
        {
            // Ticks 是纳秒
            return DateTime.Now.Ticks / 10000;
        }

        /// <summary>
        /// 获取Int64类型服务器时间，单位毫秒
        /// </summary>
        /// <returns>服务器时间</returns>
        public static Int64 getServerTime()
        {
            Int64 elapseTime = getSystemMilliSecond() - s_serverSaveTime;
            return s_serverTime + elapseTime;
        }

        /// <summary>
        /// 获取Int64类型服务器时间，单位秒
        /// </summary>
        /// <returns>服务器时间</returns>
        public static Int64 getServerTimeSecond()
        {
            Int64 elapseTime = getSystemMilliSecond() - s_serverSaveTime;
            return (s_serverTime + elapseTime) / 1000;
        }

        /// <summary>
        /// 获取DataTime类型服务器时间，单位秒
        /// </summary>
        /// <returns>服务器时间</returns>
        public static DateTime getServerDateTime()
        {
            return TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)).AddMilliseconds(getServerTime());
        }

        /// <summary>
        /// 计算指定的时间点与服务器当前时间的差值，指定时间晚于当前时间，单位秒
        /// </summary>
        /// <param name="lEndTime">指定时间点</param>
        /// <returns>时差</returns>
        public static Int64 getSubWithServerTime(Int64 lEndTime)
        {
            Int64 nNowTime = TimeUtil.getServerTime() / 1000;
            Int64 nSubTime = lEndTime - nNowTime;
            return Math.Max(0, nSubTime);
        }

        /// <summary>
        /// 计算指定的时间点与服务器当前时间的差值，指定时间早于当前时间，单位秒
        /// </summary>
        /// <param name="lBeginTime">指定时间点</param>
        /// <returns>时差</returns>
        public static Int64 getSubWithServerTimeByBeginTime(Int64 lBeginTime)
        {
            Int64 nNowTime = TimeUtil.getServerTime() / 1000;
            Int64 nSubTime = nNowTime - lBeginTime;
            return Math.Max(0, nSubTime);
        }

        public static void saveServerTime(Int64 delta)
        {
            s_serverSaveTime = getSystemMilliSecond();
            s_serverTime = delta;
        }

        /// <summary>
        /// 获取当前时间
        /// </summary>
        /// <returns>当前时间TimeData</returns>
        public static TimeData getCurTimeData()
        {
            DateTime dt = DateTime.Now;

            TimeData timeData;

            timeData.year = dt.Year;
            timeData.month = dt.Month + 1;
            timeData.day = dt.Day;

            timeData.hour = dt.Hour;
            timeData.minute = dt.Minute;
            timeData.second = dt.Second;

            return timeData;
        }

        static Int64 s_serverTime = 0;
        static Int64 s_serverSaveTime = 0;
    };

    public class Timer
    {
        /// <summary>
        /// 延迟时间
        /// </summary>
        private float _delayTime;
        /// <summary>
        /// 已经过去的时间
        /// </summary>
        private float _elapsedTime;
        /// <summary>
        /// 延迟事件
        /// </summary>
        private Action _action;
        /// <summary>
        /// 是否循环
        /// </summary>
        private bool _repeat;
        private bool _end;
        public bool end { get { return _end; } }

        public Timer(float delay, Action action, bool repeat = false)
        {
            _delayTime = delay;
            _action = action;
            _repeat = repeat;
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="dt">Time.deltaTime</param>
        public void Update(float dt)
        {
            _elapsedTime += dt;

            if (_elapsedTime >= _delayTime)
            {
                if (_repeat)
                {
                    _elapsedTime = _elapsedTime - _delayTime;
                    _action();
                }
                else
                {
                    _action();
                    _end = true;
                }
            }
        }
    }

    /// <summary>
    /// 计时器管理器
    /// </summary>
    public class TimerManager : TSingleton<TimerManager>
    {
        private List<Timer> _timers = new List<Timer>();

        /// <summary>
        /// 延迟执行程序
        /// </summary>
        /// <param name="delay">延迟时间</param>
        /// <param name="action">延迟事件</param>
        /// <param name="repeat">是否循环</param>
        public void Invoke(float delay, Action action, bool repeat = false)
        {
            _timers.Add(new Timer(delay, action, repeat));
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="dt"></param>
        public void Update(float dt)
        {
            for (int i = 0; i < _timers.Count; i++)
            {
                Timer timer = _timers[i];
                if (timer.end)
                {
                    _timers.Remove(timer);
                }
                else
                {
                    timer.Update(dt);
                }
            }
        }

        /// <summary>
        /// 清除计时器容器
        /// </summary>
        public void Clear()
        {
            _timers.Clear();
        }
    }
}